/*
 * https://gitee.com/baojuhua/dictionary.js
 *
 * @desc Dictionary
 * @param {Object}         obj 对象
 * @param {Object|String} opt 自定义配置
 *                             index:    索引
 * @return {Dictionary}
 */
export default class Dictionary {
  #raw
  #conf = { index: undefined }
  constructor(obj, opt) {
    if (opt) Object.assign(this.#conf, typeof opt == 'object' ? { ...opt } : typeof opt == 'string' ? { index: opt } : {})
    this.#raw = obj
    let dict
    if (Array.isArray(obj)) dict = Object.fromEntries(obj.map((v, i) => [this.#conf.index ? v[this.#conf.index] : i, v]))
    else dict = this.#conf.index ? Object.fromEntries(Object.values(obj).map(v => [v[this.#conf.index], v])) : obj || {}
    Object.assign(this, dict)
    Object.assign(this, dict)
  }
  /**
   * @desc  反转对象
   * @param {Object} obj 参考对象
   * @return {Object}
   */
  static reverse(obj) {
    if (Array.isArray(obj)) return obj.reverse()
    return Object.fromEntries(Object.entries(obj).map(([a, b]) => [b, a]))
  }
  /**
   * @desc  通过对象初始化对象
   * @param {Object} obj 参考对象
   * @param {Boolean} reverse 是否反转对象
   * @return {Dictionary}
   */
  static init(obj, opt) {
    return new Dictionary(obj, opt)
  }
  getRaw() {
    return this.#raw
  }
  /**
   * @desc  获取所有 key
   * @return {Array}
   */
  keys() {
    return Object.keys(this)
  }
  /**
   * @desc  获取所有value
   * @return {Array}
   */
  values() {
    return Object.values(this)
  }
  /**
   * @desc  转选项  例如 [{label:'否',value:0},{label:'是',value:1}]
   * @param {Object} opt 自定义 label,value 字段输出配置
   * @return {Array}
   */
  toOptions(opt) {
    const conf = { label: (val, key) => val, value: (val, key) => key, ...opt }
    return this.map((val, key) => {
      let item = {}
      for (let k in conf) {
        if (!conf[k]) continue
        item[k] = conf[k](val, key)
      }
      return item
    })
  }
  /**
   * @desc  输出数组  结果与 values() 输出一致
   * @return {Array}
   */
  toArray() {
    return this.map(v => v)
  }
  /**
   * @desc 自定义转换新的字典
   * @param {Object} opt 自定义输出字典的键值配置
   * @return {Object}
   */
  toDict(opt) {
    const conf = { key: (v, k) => k, value: (v, k) => v, create: Object.fromEntries, ...opt }
    let entries = this.map((val, key) => [conf.key(val, key), conf.value(val, key)])
    let dict = conf.create(entries)
    return dict
  }
  /**
   * @desc 遍历字典值并返回新的数组
   * @param {Function} c
   * @return {Array}
   */
  map(c) {
    return Object.entries(this).map((arr, index) => c(arr[1], arr[0], this))
  }
  /**
   * @desc  克隆当前字典
   * @return {Dictionary}
   */
  clone() {
    return new Dictionary(this.#raw, this.#conf)
  }
  /**
   * @desc  转换成Map
   * @return {Map}
   */
  toMap(opt) {
    return this.toDict({ ...opt, create: e => new Map(e) })
  }
}
